import { Toast } from '@/utils/util';

// 后端返回的通用响应结构
export type ResponseData<T> = {
  code: number;
  msg: string;
  data: T;
  time: string;
};

// resolve和reject不返回任何值，但通知promise更改状态
const handleResponse = <T>(res: any, resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => {
  // 分离了验证状态码逻辑
  if (isSuccessStatusCode(res.statusCode) && res.data.code == 1) {
    resolve(res.data);
  } else {
    // 分离了报错状态码逻辑
    showErrorToast(res.data);
    reject(res);
  }
};

const handleError = (err: any, reject: (reason?: any) => void) => {
  Toast('网络可能开小差了~');
  reject(err);
};

const isSuccessStatusCode = (statusCode: number) => {
  return statusCode >= 200 && statusCode < 300;
};

const showErrorToast = <T>(data: ResponseData<T>) => {
  Toast(data.msg || '请求错误');
};

const request = <T>(
  url: string,
  method: 'GET' | 'POST',
  data?: string | AnyObject | ArrayBuffer
): Promise<ResponseData<T>> => {
  const controller = new AbortController();
  const signal = controller.signal;

  return new Promise((reslove, reject) => {
    uni.request({
      url: process.env.VUE_APP_BASEHOST + url,
      header: {
        Authorization: uni.getStorageSync('outsideToken'),
      },
      method,
      data,
      success: res => {
        // 成功响应
        handleResponse(res, reslove, reject);
      },
      fail: err => {
        if (!signal.aborted) {
          handleError(err, reject);
        }
      },
    });

    if (!signal.aborted) {
      controller.abort(); // 取消请求
      console.log('Request was cancelled');
    }
  });
};

// 上传图片
export const uploadRequest = <T>(
  url: string,
  tempFilePaths: any[],
  formData?: Record<string, any>
): Promise<ResponseData<T>> =>
  new Promise((reslove, reject) => {
    for (let i = 0; i < tempFilePaths.length; i++) {
      const filePath = tempFilePaths[i];
      uni.uploadFile({
        url: process.env.VUE_APP_BASEHOST + url,
        header: {
          Authorization: uni.getStorageSync('outsideToken'),
        },
        filePath,
        name: 'file',
        formData,
        success: res => {
          // console.log(res);
          res.data = JSON.parse(res.data);
          handleResponse(res, reslove, reject);
        },
        fail: err => {
          console.error(err);
          reject(err);
        },
      });
    }
  });

export default request;
